﻿using System.IO;
using Adventure.Server.Data;
using Adventure.Server.Library;
using Adventure.Server.Manager;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Adventure.Tests
{
    /// <summary>
    /// Tests the object manager
    /// </summary>
    [TestClass]
    public class ObjectManagerTests
    {
        /// <summary>
        /// Gets or sets the test context.
        /// </summary>
        public TestContext TestContext { get; set; }

        /// <summary>
        /// Gets or sets the temporary folder for the tests.
        /// </summary>
        public static string TempFolder { get; set; }

        /// <summary>
        /// Initialize the Tests in this Class.
        /// </summary>
        [ClassInitialize]
        public static void Init(TestContext testContext)
        {
            // Get a temporary folder, remove it if it exists and create it afterwards.
            TempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            var directoryInfo = new DirectoryInfo(TempFolder);
            if (directoryInfo.Exists) directoryInfo.Delete(true);
            directoryInfo.Create();
        }

        /// <summary>
        /// Cleanup after the tests.
        /// </summary>
        [ClassCleanup]
        public static void CleanUp()
        {
            var directoryInfo = new DirectoryInfo(TempFolder);
            if (directoryInfo.Exists) directoryInfo.Delete(true);
        }

        /// <summary>
        /// Tests the ObjectManager
        /// </summary>
        [TestMethod]
        public void TestObjectManager()
        {
            // Create the object manager and initialize it.
            ObjectManager manager = new ObjectManager();
            IDataAdapter adapter = new TextFileDataAdapter();
            adapter.SetSource(TempFolder);
            manager.SetDataAdapter(adapter);
            SavedObject.SetObjectManager(manager);

            // Create an object
            SavedObject obj = manager.CreateObject(HelperFunctions.CreateAttributes("obj/test1"));
            Assert.IsNotNull(obj);

            // Create same object again => Should fail
            SavedObject obj2 = manager.CreateObject(HelperFunctions.CreateAttributes("obj/test1"));
            Assert.IsNull(obj2);

            // Get the first object and make sure that both objects are the same reference
            SavedObject obj3 = manager.GetObject(obj.Id);
            Assert.IsNotNull(obj3);
            Assert.IsTrue(ReferenceEquals(obj, obj3));

            // Save object
            Assert.IsTrue(obj.IsChanged);
            Assert.IsTrue(obj3.IsChanged);
            obj.Save();
            Assert.IsFalse(obj.IsChanged);
            Assert.IsFalse(obj3.IsChanged);

            // Disposing the objects, check referece count
            Assert.AreEqual(2, obj.ReferenceCounter);
            obj.Dispose();
            Assert.AreEqual(1, obj.ReferenceCounter);
            obj3.Dispose();
            Assert.AreEqual(0, obj.ReferenceCounter);

            // Test deletion of object
            manager.Delete(obj.Id);

            // Make sure that the object cannot be loaded any longer
            Assert.IsNull(manager.GetObject(obj.Id));
        }
    }
}
